package educrypt.gui.components;

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToggleButton;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset;

import educrypt.gui.view.AnalysisResultView;
import educrypt.gui.view.EducryptFileChooserView;
import educrypt.i18n.Messages;
import educrypt.resources.EduCryptResources;

class AnalysisResultPanel extends EducryptPanel implements AnalysisResultView {

	private static final long serialVersionUID = 4942808416400332353L;

	private FrequencyChart resultChart;
	private JTable resultTable;

	private JPanel resultPanel;

	private JToggleButton btnShowChart;
	private JToggleButton btnShowTable;

	private ButtonGroup groupButtonShowResults;

	private JPanel tableResultPanel;
	private JButton btnSaveResult;

	private EducryptFileChooser saveFileDialog;

	public AnalysisResultPanel() {
		this.setSize(750, 410);
		this.setPreferredSize(this.getSize());

		setLayout(new BorderLayout(0, 0));

		/* North Panel */
		JPanel northPanel = new JPanel();
		northPanel.setSize(750, 40);
		northPanel.setPreferredSize(northPanel.getSize());
		add(northPanel, BorderLayout.NORTH);
		northPanel.setLayout(null);

		JLabel lblAnalysisResult = new JLabel(
				Messages.getString("guiAnalysisResults"));
		lblAnalysisResult.setBounds(31, 11, 318, 19);
		northPanel.add(lblAnalysisResult);
		lblAnalysisResult.setFont(new Font("Tahoma", Font.BOLD, 15));
		/* END North Panel */

		/* South Panel */
		JPanel southPanel = new JPanel();
		southPanel.setSize(750, 50);
		southPanel.setPreferredSize(southPanel.getSize());
		add(southPanel, BorderLayout.SOUTH);
		southPanel.setLayout(null);

		ImageIcon iconShowChart = new ImageIcon(
				EduCryptResources.getImageURL("showChart32.png"));

		btnShowChart = new JToggleButton(iconShowChart);
		btnShowChart.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				showChart(true);
			}
		});

		btnShowChart.setBounds(330, 6, 38, 38);
		southPanel.add(btnShowChart);

		ImageIcon iconShowText = new ImageIcon(
				EduCryptResources.getImageURL("showLetters32.png"));

		btnShowTable = new JToggleButton(iconShowText, true);
		btnShowTable.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				showTable(true);
			}
		});

		btnShowTable.setBounds(384, 6, 38, 38);
		southPanel.add(btnShowTable);

		groupButtonShowResults = new ButtonGroup();
		groupButtonShowResults.add(btnShowChart);
		groupButtonShowResults.add(btnShowTable);

		tableResultPanel = new JPanel();
		tableResultPanel.setLayout(null);

		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setBounds(32, 0, 652, 320);
		tableResultPanel.add(scrollPane);

		resultTable = new JTable(new FrequencyTableModel());
		scrollPane.setViewportView(resultTable);

		// Show the text centered
		DefaultTableCellRenderer dtcr = new DefaultTableCellRenderer();
		dtcr.setHorizontalAlignment(DefaultTableCellRenderer.CENTER);
		resultTable.setDefaultRenderer(Object.class, dtcr);

		ImageIcon saveIcon = new ImageIcon(
				EduCryptResources.getImageURL("save24.png"));

		btnSaveResult = new JButton(saveIcon);
		btnSaveResult.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
			}
		});
		btnSaveResult.setBounds(695, 292, 28, 28);
		tableResultPanel.add(btnSaveResult);
		/* END South Panel */

		resultPanel = new JPanel();

		saveFileDialog = new EducryptFileChooser(btnSaveResult);
		saveFileDialog.setCsvMode();

		setPanelEnabled(false);
	}

	@Override
	public void setPanelEnabled(boolean b) {
		super.setPanelEnabled(b);
		if (b == false) {
			this.showResult(false);
		}
	}

	@Override
	public void addListener(ActionListener ctr) {
		btnSaveResult.setActionCommand(SAVE_RESULT);
		btnSaveResult.addActionListener(ctr);

		saveFileDialog.addListener(ctr);
	}

	@Override
	public void initializeResult(String textName) {
		resultChart = new FrequencyChart(textName);
		FrequencyTableModel ftm = (FrequencyTableModel) resultTable.getModel();
		ftm.removeRows();
	}

	@Override
	public void addResult(String symbol, double percentage,
			double absoluteFrequency) {
		addResultRow(symbol, percentage, absoluteFrequency);
		resultChart.addTag(symbol);
		resultChart.addValue(percentage);
	}

	private void addResultRow(String symbol, double percentage,
			double absoluteFrequency) {
		DecimalFormat twodecimal = new DecimalFormat("#.##");
		DecimalFormat zerodecimal = new DecimalFormat("#");

		int row = resultTable.getRowCount();
		resultTable.setValueAt(symbol, row, 0);
		resultTable.setValueAt(zerodecimal.format(absoluteFrequency), row, 1);
		resultTable.setValueAt(twodecimal.format(percentage), row, 2);
	}

	@Override
	public void showResult(boolean show) {
		boolean isChartSelected = this.btnShowChart.isSelected();
		if (isChartSelected) {
			this.showChart(show);
		} else {
			this.showTable(show);
		}
	}

	@Override
	public void showChart(boolean show) {
		this.remove(resultPanel);
		if (show) {
			resultPanel = resultChart.generateChart();
		} else {
			resultPanel = new JPanel();
		}
		this.add(resultPanel, BorderLayout.CENTER);
		this.repaint();
		this.validate();
	}

	@Override
	public void showTable(boolean show) {
		this.remove(resultPanel);
		if (show) {
			resultPanel = tableResultPanel;
		} else {
			resultPanel = new JPanel();
		}
		this.add(resultPanel, BorderLayout.CENTER);
		this.repaint();
		this.validate();
	}

	@Override
	public EducryptFileChooserView getSaveFileDialog() {
		return saveFileDialog;
	}

	public class FrequencyChart {
		private static final int MAX_TAG_TO_SHOW = 48;

		private List<String> tags;
		private List<Double> values;
		private String textName;

		public FrequencyChart(String textName) {
			this.tags = new ArrayList<String>();
			this.values = new ArrayList<Double>();
			this.textName = textName;
		}

		public void addTag(String tag) {
			this.tags.add(tag);
		}

		public void addValue(double value) {
			this.values.add(value);
		}

		public JPanel generateChart() {
			assert this.tags.size() == this.values.size();

			DefaultCategoryDataset dataset = new DefaultCategoryDataset();
			for (int i = 0; i < this.tags.size(); i++) {
				dataset.addValue(this.values.get(i), this.tags.get(i), "");
			}

			// If there is a lot of tag the legend, it should not be shown
			boolean includeLegend = tags.size() <= MAX_TAG_TO_SHOW;

			String chartTitle = Messages.getString("guiChartTitle") + ": \""
					+ this.textName + "\"";
			String xAxisLabel = Messages.getString("guiChartXLabel");
			String yAxisLabel = Messages.getString("guiChartYLabel");

			JFreeChart chart = ChartFactory.createBarChart(chartTitle, // chart
					// title
					xAxisLabel, // domain axis label
					yAxisLabel, // range axis label
					dataset, // data
					PlotOrientation.VERTICAL, // orientation
					includeLegend, // include legend
					true, // tooltips?
					false // URLs?
					);

			// Set the title font and size
			chart.setTitle(new org.jfree.chart.title.TextTitle(chartTitle,
					new java.awt.Font("Thaoma", java.awt.Font.BOLD, 14)));

			chart.setBackgroundPaint(null); // transparent background
			ChartPanel panel = new ChartPanel(chart);
			return panel;
		}
	}

	public class FrequencyTableModel extends AbstractTableModel {

		private static final long serialVersionUID = -8476455827251864808L;

		private String[] columnNames = {
				Messages.getString("guiAnalysisResultSymbol"),
				Messages.getString("guiAnalysisResultFrequency"),
				Messages.getString("guiAnalysisResultPercentage") };

		private List<List<Object>> data = new ArrayList<List<Object>>();

		@Override
		public int getColumnCount() {
			return columnNames.length;
		}

		@Override
		public String getColumnName(int col) {
			return columnNames[col];
		}

		@Override
		public int getRowCount() {
			return data.size();
		}

		@Override
		public void setValueAt(Object value, int row, int col) {
			while (data.size() < row + 1) {
				data.add(new ArrayList<Object>());
			}
			List<Object> columns = data.get(row);
			while (columns.size() < col + 1) {
				columns.add(new Object());
			}
			columns.set(col, value);

			fireTableCellUpdated(row, col);
		}

		@Override
		public Object getValueAt(int row, int col) {
			return data.get(row).get(col);
		}

		public void removeRows() {
			int rowCount = data.size();
			if (rowCount > 0) {
				int lastRow = rowCount - 1;
				data.clear();
				fireTableRowsDeleted(0, lastRow);
			}
		}
	}

}
